using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for hints.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "HintAttributes", Namespace = "SharpGL.SceneGraph")]
    public class HintAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.Hint;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private HintMode? perspectiveCorrectionHint;
        [DataMember()]
        private HintMode? pointSmoothHint;
        [DataMember()]
        private HintMode? lineSmoothHint;
        [DataMember()]
        private HintMode? polygonSmoothHint;
        [DataMember()]
        private HintMode? fogHint;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="HintAttributes"/> class.
        /// </summary>
        public HintAttributes()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return
                perspectiveCorrectionHint.HasValue ||
                pointSmoothHint.HasValue ||
                lineSmoothHint.HasValue ||
                polygonSmoothHint.HasValue ||
                fogHint.HasValue;
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            perspectiveCorrectionHint = null;
            pointSmoothHint = null;
            lineSmoothHint = null;
            polygonSmoothHint = null;
            fogHint = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (perspectiveCorrectionHint.HasValue) gl.Hint(HintTarget.PerspectiveCorrection, perspectiveCorrectionHint.Value);
            if (pointSmoothHint.HasValue) gl.Hint(HintTarget.LineSmooth, pointSmoothHint.Value);
            if (lineSmoothHint.HasValue) gl.Hint(HintTarget.PointSmooth, lineSmoothHint.Value);
            if (polygonSmoothHint.HasValue) gl.Hint(HintTarget.PolygonSmooth, polygonSmoothHint.Value);
            if (fogHint.HasValue) gl.Hint(HintTarget.Fog, fogHint.Value);
        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets or sets the perspective correction hint.
        /// </summary>
        /// <value>
        /// The perspective correction hint.
        /// </value>
        [Description("Perspective correction"), Category("Hint")]
        public HintMode? PerspectiveCorrectionHint
        {
            get { return perspectiveCorrectionHint; }
            set
            {
                if (perspectiveCorrectionHint != value)
                {
                    perspectiveCorrectionHint = value;

                    NotifyPropertyChanged("PerspectiveCorrectionHint");
                }
            }
        }

        /// <summary>
        /// Gets or sets the point smooth hint.
        /// </summary>
        /// <value>
        /// The point smooth hint.
        /// </value>
        [Description("Perspective correction"), Category("Hint")]
        public HintMode? PointSmoothHint
        {
            get { return pointSmoothHint; }
            set
            {
                if (pointSmoothHint != value)
                {
                    pointSmoothHint = value;

                    NotifyPropertyChanged("PointSmoothHint");
                }
            }
        }

        /// <summary>
        /// Gets or sets the line smooth hint.
        /// </summary>
        /// <value>
        /// The line smooth hint.
        /// </value>
        [Description("Perspective correction"), Category("Hint")]
        public HintMode? LineSmoothHint
        {
            get { return lineSmoothHint; }
            set
            {
                if (lineSmoothHint != value)
                {
                    lineSmoothHint = value;

                    NotifyPropertyChanged("LineSmoothHint");
                }
            }
        }

        /// <summary>
        /// Gets or sets the polygon smooth hint.
        /// </summary>
        /// <value>
        /// The polygon smooth hint.
        /// </value>
        [Description("Perspective correction"), Category("Hint")]
        public HintMode? PolygonSmoothHint
        {
            get { return polygonSmoothHint; }
            set
            {
                if (polygonSmoothHint != value)
                {
                    polygonSmoothHint = value;

                    NotifyPropertyChanged("PolygonSmoothHint");
                }
            }
        }

        /// <summary>
        /// Gets or sets the fog hint.
        /// </summary>
        /// <value>
        /// The fog hint.
        /// </value>
        [Description("Perspective correction"), Category("Hint")]
        public HintMode? FogHint
        {
            get { return fogHint; }
            set
            {
                if (fogHint != value)
                {
                    fogHint = value;

                    NotifyPropertyChanged("HintMode");
                }
            }
        }

        #endregion Public Properties
    }
}
